/**
 * author: Hanflyee  flyee1980@163.com
 * vision: v1.0
 * data: 2009-7-9
 */
package com.flyee.service{
	
	import com.flyee.controller.CharacterCartoonController;
	import com.flyee.controller.CharacterSkillController;
	import com.flyee.controller.CharactorMoveController;
	import com.flyee.controller.MonsterController;
	import com.flyee.controller.SceneController;
	import com.flyee.controller.SkillPanelController;
	import com.flyee.controller.timer.CartoonTimer;
	import com.flyee.controller.timer.WalkTimer;
	import com.flyee.controller.tools.cartoon.model.AppearanceConfig;
	import com.flyee.controller.tools.path.AStar;
	import com.flyee.io.socket.CommandUpSender;
	import com.flyee.model.Charactor;
	import com.flyee.model.Monster;
	import com.flyee.ro.commandup.EquipChangeUp;
	import com.flyee.ro.commandup.JoinRoomUp;
	import com.flyee.ro.commandup.LoginUp;
	import com.flyee.ro.commandup.LogoutUp;
	import com.flyee.ro.commandup.QuitRoomUp;
	import com.flyee.ro.commandup.RoadPathUp;
	import com.flyee.ro.commandup.SkillScopeUp;
	import com.flyee.ro.commandup.SkillSingleUp;
	import com.flyee.ro.rpc.AvatarRO;
	import com.flyee.service.pool.ObjectCollection;
	import com.flyee.utils.CoodinateUtil;
	import com.flyee.utils.MyLog;
	import com.flyee.utils.Obsevable;
	import com.flyee.utils.Obsever;
	import com.flyee.viewer.CharactorViewer;
	
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;	
	
	/**
	 * C层，人物相关管理类
	 */
	public class CharactorService implements Obsever{
		[Inject]
		public var commandSender : CommandUpSender;
		[Inject]
		public var moveController : CharactorMoveController;
		[Inject]
		public var cartoonController : CharacterCartoonController;
		[Inject]
		public var skillController : CharacterSkillController;
		[Inject]
		public var skillPanelController : SkillPanelController;
		[Inject]
		public var monsterController : MonsterController;
		[Inject]
		public var sceneController : SceneController;
				
		public function CharactorService(){
		}

		/**注册观察者 各个CONTROLLER之间的通信*/
		public function registeObsever() : void {
//			moveController.addObserver(SceneService.getInstance().sceneController);
			moveController.addObserver(cartoonController);
		}
		
		/**
	     * 接到被观察者通知后执行
	     * @param o 被观察者
	     * @param command 指令
	     * @param args 参数
	     */
	    public function execute(o : Obsevable, command : String = null, args : * = null) : void {
	        switch (command) {
	            case "choiceAvatar" :
	                choiceAvatar();
	                break;
	            case "initAvatars" :
	                initAvatars(args[0]);
	                break;
	            case "addAvatar" :
	                addAvatar(args[0]);
	                break;
	            case "move" :
	                move(args[0],args[1],args[2],args[3]);
	                break;
	            case "synchronize" :
//	            	synchronize(args[0], args[1], args[2],args[3]);
	            	break;
	            case "executeSkill" :
	                executeSkill(args[0],args[1],args[2],args[3],args[4]);
	                break;
	            case "quitRoom" :
	                quitRoom(args[0]);
	                break;
                case "changeEquip" :
	                changeEquip(args[0], args[1]);
	                break;
	            default :
	                //MyLog.debug("command is null!");
	                break;
	        }
	    }
		
		/**登入系统*/
		public function login(c : Charactor) : void {
			var loginUp : LoginUp = new LoginUp();
			loginUp.handler = "loginHandler";
			loginUp.sceneId = c.sceneId;
			loginUp.sceneInstanceId = c.sceneInstanceId;
			loginUp.sender = c.gcode;
			commandSender.send(loginUp);
			MyLog.debug("login waiting");
		}
		
		/**退出*/
		public function logout() : void {
			var logoutUp : LogoutUp = new LogoutUp();
			logoutUp.sender = ObjectCollection.master.id;
			logoutUp.sceneId = ObjectCollection.master.sceneId;
			logoutUp.sceneInstanceId = ObjectCollection.master.sceneInstanceId;
			commandSender.send(logoutUp);
			MyLog.debug("logout!");
		}
		
		/**退出场景*/
		public function quitRoom(id : String) : void {
			var char : Charactor = ObjectCollection.getCharacter(id);
			if(char == null) return;
			var charUI : CharactorViewer = ObjectCollection.getCharacterViewerByMid(char.mid);
			ObjectCollection.charactorMap.remove(char.mid);
			ObjectCollection.currentSceneViewer.componentLayer.removeChild(charUI);
			ObjectCollection.charactorViewerMap.remove(charUI.vid);
			ObjectCollection.removeRelationByMid(char.mid);
			var cartoonTimer : CartoonTimer = ObjectCollection.cartoonTimerMap.remove(charUI.vid) as CartoonTimer;
			cartoonTimer.dispose();
			var moveTimer : WalkTimer = ObjectCollection.moveTimerMap.remove(charUI.vid) as WalkTimer;
			if(moveTimer != null)
				moveTimer.dispose();
			if(ObjectCollection.master.target == char){
				ObjectCollection.targetWindowViewer.visible = false;
				ObjectCollection.master.target = null;
			}
			charUI.dispose();
		}
		
		/**登陆成功,选择已创建的角色（由于功能未做，直接执行进入场景）*/
		public function choiceAvatar() : void {
			var joinRoomUp : JoinRoomUp = new JoinRoomUp();
			joinRoomUp.handler = "joinRoomHandler";
			joinRoomUp.sceneId = ObjectCollection.master.sceneId;
			joinRoomUp.sceneInstanceId = ObjectCollection.master.sceneInstanceId;
			joinRoomUp.sender = ObjectCollection.master.gcode;
			commandSender.send(joinRoomUp);
			MyLog.debug("Join room waiting");
		}
		
		/**进入场景*/
		public function enterInScene() : void {
			var charUI : CharactorViewer;
			if(ObjectCollection.masterViewer != null)
				charUI = ObjectCollection.masterViewer;
			else
				charUI = cartoonController.initCharacterViewer(ObjectCollection.master);
			moveController.addCharactor(ObjectCollection.master, charUI, ObjectCollection.currentSceneViewer.componentLayer);
			monsterController.init();
			skillPanelController.init();

		}
		
		/**初始化场景中玩家*/
		public function initAvatars(avatars : Array) : void {
			enterInScene();
			addAvatars(avatars);
		}
		
		/**加载新进入场景玩家*/
		public function addAvatars(playerArr : Array) : void {
			//取得进入的玩家数组
			for each(var avatar : AvatarRO in playerArr){
				addAvatar(avatar);
			}
		}
		
		public function addAvatar(avatar : AvatarRO) : void {
			var player : Charactor = new Charactor();
			player.id = avatar.avatarId;
			player.gcode = avatar.avatarId;
			if(avatar.hp<0)
				avatar.hp = 0;
			player.hp = avatar.hp;
			player.mySex = 0;
			player.name = "游客" + avatar.avatarId;
			player.sceneId = ObjectCollection.DEFAULT_SCENE_ID;
			player.x = avatar.startX;
			player.y = avatar.startY - 22;	
			MyLog.debug(player.id + " enter scene.");
			ObjectCollection.charactorMap.put(player.mid, player);
			var charUI : CharactorViewer = cartoonController.initCharacterViewer(player);			
			charUI.resetHP(player.hp);	
			moveController.addCharactor(player, charUI, ObjectCollection.currentSceneViewer.componentLayer);
			if(player.hp == 0){
				cartoonController.playerDie(charUI);
			}
		}
		
		/**切换场景*/
		public function switchScene(sceneID : String, charX : Number, charY : Number) : void {
			moveController.depthTimer.stop();
			//销毁现场景
			for each(var char : Charactor in ObjectCollection.charactorMap.values()){
				this.quitRoom(char.id);
			}
			sceneController.unloadScene();
			//发出退出现场景指令
			var quitRoomCmd : QuitRoomUp = new QuitRoomUp();
			quitRoomCmd.sender = ObjectCollection.master.gcode;
			quitRoomCmd.sceneId = ObjectCollection.master.sceneId;
			quitRoomCmd.sceneInstanceId = ObjectCollection.master.sceneInstanceId;
			commandSender.send(quitRoomCmd);
			//发出进入新场景指令
			ObjectCollection.master.sceneId = sceneID;
			ObjectCollection.master.sceneInstanceId = sceneID;
			var joinRoomUp : JoinRoomUp = new JoinRoomUp();
			joinRoomUp.handler = "joinRoomHandler";
			joinRoomUp.sceneId = sceneID;
			joinRoomUp.sceneInstanceId = sceneID;
			joinRoomUp.sender = ObjectCollection.master.gcode;
			commandSender.send(joinRoomUp);
		}

		/**客户端寻路*/
		public function requestPath(event : MouseEvent) : void {
			if(ObjectCollection.master.hp == 0) return ;
//			if(ObjectCollection.master.skillStatus) return ;
			if(ObjectCollection.master.waitMoveStatus) return ;
			this.moveController.pausePlayerMove(ObjectCollection.masterViewer);
			var start : Point = new Point(ObjectCollection.master.x, ObjectCollection.master.y + 22);
			//转换坐标系
			var end : Point = CoodinateUtil.convertToObliqueXY(new Point(
													ObjectCollection.currentSceneViewer.mouseX - 40, 
													ObjectCollection.currentSceneViewer.mouseY)); 
			end.y += 22;
//			var aStar : AStar = new AStar(ObjectCollection.mapData);
			var pathArr : Array = AStar.findPath(start.y, start.x, end.y, end.x);
			if(pathArr == null) return ;
			//发出请求
			var cmd : RoadPathUp = new RoadPathUp();
			cmd.startX = start.x;
			cmd.startY = start.y;
			cmd.targetX = end.x;
			cmd.targetY = end.y;
			cmd.panes = pathArr;
			cmd.sceneId = ObjectCollection.master.sceneId;
			cmd.sceneInstanceId = ObjectCollection.master.sceneInstanceId;
			cmd.sender = ObjectCollection.master.id;
			commandSender.send(cmd);
			move(ObjectCollection.master.gcode, start.x, start.y, pathArr, true);
		}
		
		/**人物行走*/
		public function move(playerId : String, startX : int, startY : int, pathArr : Array, b : Boolean = false) : void {
			if(playerId == ObjectCollection.master.gcode)
				if(!b)
					return ;
			var player : Charactor = ObjectCollection.getCharacter(playerId);
			if(player == null) return ;
			if(player.hp == 0) return ;
			var playerV : CharactorViewer = ObjectCollection.getCharacterViewerByMid(player.mid);
			if(moveController.checkSynchronize(player, startX, startY-22)){
				moveController.move(player, playerV, pathArr);
			}else{
				moveController.synchronizeHandler(player, playerV, startX, startY-22, pathArr);
			}
		}
		
		/**位置同步*/
		public function synchronize(playerId : String, x : Number, y : Number, pathArr : Array) : void {
			var player : Charactor = ObjectCollection.getCharacter(playerId);
			if(player == null) return ;
			var playerV : CharactorViewer = ObjectCollection.getCharacterViewerByMid(player.mid);
			if(moveController.checkSynchronize(player, x, y-22)){
				moveController.move(player, playerV, pathArr);
			}else{
				moveController.synchronizeHandler(player, playerV, x, y-22, pathArr);
			}
		}
		
		/**设置人物可见*/
		public function setPlayerVisible(value : Boolean) : void {
			cartoonController.setPlayersVisible(value);
		}
		
		/**
		 * 响应快捷键 发出技能 
		 */
		public function keyDownHandler(event : KeyboardEvent) : void {
			sendSkill(event.keyCode - 49);
		}
		
		/**
		 * 快捷方式，上传攻击指令到服务器
		 * 暂时把UIController的代码放这里 
		 */
		public function sendSkill(id : int) : void {
			if(ObjectCollection.master.hp == 0 
//				|| ObjectCollection.master.skillStatus
				|| !ObjectCollection.master.cooldown) return ;

			
			switch(id){                     
                case 0 :
                	//快捷键1
                	//模拟服务器传回的数据
                	if(ObjectCollection.master.target == null || ObjectCollection.master.target == ObjectCollection.master) return ;
                	if(ObjectCollection.master.target.hp == 0) return ;
                	if(CoodinateUtil.checkDistance(ObjectCollection.master.x
                								 , ObjectCollection.master.y
                								 , ObjectCollection.master.target.x
                								 , ObjectCollection.master.target.y)>1) 
                		return ;
                	ObjectCollection.master.skillStatus = true;
					var cmd1 : SkillSingleUp = new SkillSingleUp();
					cmd1.sender = ObjectCollection.master.gcode;
					cmd1.sceneId = ObjectCollection.master.sceneId;
					cmd1.sceneInstanceId = ObjectCollection.master.sceneInstanceId;
					cmd1.sourceId = ObjectCollection.master.gcode;
					cmd1.targetId = ObjectCollection.master.target.gcode;
					cmd1.skillId = "1";
					commandSender.send(cmd1);
                	break;
                case 1 :
                	//快捷键2
                	if(ObjectCollection.master.target == null || ObjectCollection.master.target == ObjectCollection.master) return ;
                	if(ObjectCollection.master.target.hp == 0) return ;
                	if(CoodinateUtil.checkDistance(ObjectCollection.master.x
                								 , ObjectCollection.master.y
                								 , ObjectCollection.master.target.x
                								 , ObjectCollection.master.target.y)>8) 
                		return ;
                	ObjectCollection.master.skillStatus = true;
					var cmd2 : SkillSingleUp = new SkillSingleUp();
					cmd2.sender = ObjectCollection.master.gcode;
					cmd2.sceneId = ObjectCollection.master.sceneId;
					cmd2.sceneInstanceId = ObjectCollection.master.sceneInstanceId;
					cmd2.sourceId = ObjectCollection.master.gcode;
					cmd2.targetId = ObjectCollection.master.target.gcode;
					cmd2.skillId = "2";
					commandSender.send(cmd2);
                	break;
               	case 2 :
               		//快捷键3
               		var target : Point = CoodinateUtil.convertToObliqueXY(new Point(
                									ObjectCollection.currentSceneViewer.mouseX - 40, 
													ObjectCollection.currentSceneViewer.mouseY));
               		if(CoodinateUtil.checkDistance(ObjectCollection.master.x
                								 , ObjectCollection.master.y
                								 , target.x
                								 , target.y)>8) 
               			return ;
                	ObjectCollection.master.skillStatus = true;                	
					var cmd3 : SkillScopeUp = new SkillScopeUp();
					cmd3.sender = ObjectCollection.master.gcode;
					cmd3.sceneId = ObjectCollection.master.sceneId;
					cmd3.sceneInstanceId = ObjectCollection.master.sceneInstanceId;
					cmd3.sourceId = ObjectCollection.master.gcode;
					cmd3.skillId = "3";
					cmd3.targetX = target.x.toString();
					cmd3.targetY = target.y.toString();
					cmd3.targets = new Array();
					for each(var enemy : Charactor in ObjectCollection.charactorMap.values()){
						if(CoodinateUtil.checkDistance(target.x, target.y, enemy.x, enemy.y)<=1 && enemy.hp >0)
							cmd3.targets.push(enemy.gcode);
					}
					commandSender.send(cmd3);
                	break;
            	case 3 :
            		//快捷键4
//            		if(ObjectCollection.master.target != null && ObjectCollection.master.target.hp == 0) return ;
            		if(ObjectCollection.master.target == null){
            			
            		}else{
            			if(ObjectCollection.master.target.hp == 0)
            				return ;
            		}
            		
            		ObjectCollection.master.skillStatus = true;                 		       	
					var cmd4 : SkillSingleUp = new SkillSingleUp();
					cmd4.sender = ObjectCollection.master.gcode;
					cmd4.sceneId = ObjectCollection.master.sceneId;
					cmd4.sceneInstanceId = ObjectCollection.master.sceneInstanceId;
					cmd4.sourceId = ObjectCollection.master.gcode;
					if(ObjectCollection.master.target==null){
						cmd4.targetId = ObjectCollection.master.gcode;
					}else if(ObjectCollection.master.target is Monster){
            			cmd4.targetId = ObjectCollection.master.gcode;
            		}else{
						cmd4.targetId = ObjectCollection.master.target.gcode;
            		}
					cmd4.skillId = "4";
					commandSender.send(cmd4);
                	break;
                case 4 :
                	//快捷键5
                	if(ObjectCollection.master.hp == 0) return ;
                	ObjectCollection.master.skillStatus = true;
                	var cmd5 : SkillSingleUp = new SkillSingleUp();
					cmd5.sender = ObjectCollection.master.gcode;
					cmd5.sceneId = ObjectCollection.master.sceneId;
					cmd5.sceneInstanceId = ObjectCollection.master.sceneInstanceId;
					cmd5.sourceId = ObjectCollection.master.gcode;
					cmd5.targetId = ObjectCollection.master.gcode;
					cmd5.skillId = "5";
					commandSender.send(cmd5);
					break;
            	default : 
            		return ;            	
   			}	
   			ObjectCollection.masterCDTimer.start();
   			moveController.pausePlayerMove(ObjectCollection.masterViewer);
			cartoonController.changeActionDirect(ObjectCollection.masterViewer, AppearanceConfig.MOVE_BY_READY);
		}
		
		public function sendChangeEquip(equipId:String):void{
			var cmd:EquipChangeUp = new EquipChangeUp();
			cmd.playerId = ObjectCollection.master.gcode;
			cmd.equipId = equipId;
			cmd.sender = ObjectCollection.master.gcode;
			cmd.sceneId = ObjectCollection.master.sceneId;
			cmd.sceneInstanceId = ObjectCollection.master.sceneInstanceId;
			commandSender.send(cmd);
		}
		
		/**
		 * 人物攻击 
		 */
		public function executeSkill(srcPlayerId : String, targetO : Object, skill : int, damage : int, enemys : Array = null) : void {
			var player : Charactor;
			var playerViewer : CharactorViewer;
			var target : Charactor;
			var targetViewer : CharactorViewer
			var direct : int;
			if(srcPlayerId == ObjectCollection.master.gcode){
				player = ObjectCollection.master;
				playerViewer = ObjectCollection.masterViewer;				
			}else{
				player = ObjectCollection.getCharacter(srcPlayerId);
				playerViewer = ObjectCollection.getCharacterViewerByMid(player.mid);			
				
			}
			if(player.hp == 0) return ;
			if(targetO is String){
				if(targetO.toString() == ObjectCollection.master.gcode){
					target = ObjectCollection.master;
					targetViewer = ObjectCollection.masterViewer;
				}else{
					target = ObjectCollection.getCharacter(targetO.toString());
					targetViewer = ObjectCollection.getCharacterViewerByMid(target.mid)
				}
				moveController.pausePlayerMove(playerViewer);
				direct = CoodinateUtil.calculateDirection(target.x - player.x, target.y - player.y);
			}else{
				direct = CoodinateUtil.calculateDirection(targetO.x - player.x, targetO.y - player.y);
			}
			switch(skill){
				case 1 : 				
					if(target.hp==0){
						player.skillStatus = false;
						return;	
					}
					MyLog.debug("fight close " + direct);
					player.skillStatus = true;
					cartoonController.changeActionDirect(playerViewer, AppearanceConfig.MOVE_BY_FIGHT, direct, 0);
					skillController.fightSkill(playerViewer, target, targetViewer, damage);
					break ;
				case 2 : 
					if(target.hp==0){
						player.skillStatus = false;
						return;	
					}
					MyLog.debug("shoot target " + direct);
					player.skillStatus = true;
					cartoonController.changeActionDirect(playerViewer, AppearanceConfig.MOVE_BY_MAGICE, direct, 0);
					skillController.showShootSkill(playerViewer,targetViewer, target, damage);
					break ;
				case 3 :
					MyLog.debug("area magic" + direct);
					player.skillStatus = true;
					cartoonController.changeActionDirect(playerViewer, AppearanceConfig.MOVE_BY_MAGICE, direct, 0);
					skillController.showAreaMagic(playerViewer, targetO as Point, enemys, damage);
					break ;
				case 4 : 
					if(target.hp==0){
						player.skillStatus = false;
						return;	
					}
					MyLog.debug("magic buff" + direct);
					player.skillStatus = true;
					cartoonController.changeActionDirect(playerViewer, AppearanceConfig.MOVE_BY_MAGICE, direct, 0);
					skillController.showBuffMagic(playerViewer,targetViewer);
					break;
				case 5 :
					MyLog.debug("using item" + direct);
					player.skillStatus = false;
					skillController.dealResumeHandler(player,300);
					break;
				default : 
					break ;
			}

		}
		
		public function changeEquip(playerId : String, equipId : String) : void {
			var player : Charactor;
			var playerViewer : CharactorViewer;
			var target : Charactor;
			var targetViewer : CharactorViewer
			var direct : int;
			if(playerId == ObjectCollection.master.gcode){
				player = ObjectCollection.master;
				playerViewer = ObjectCollection.masterViewer;				
			}else{
				player = ObjectCollection.getCharacter(playerId);
				playerViewer = ObjectCollection.getCharacterViewerByMid(player.mid);			
				
			}
			ObjectCollection.master.equipID = equipId;
			cartoonController.loadCharacterPlate(player,playerViewer,equipId);
		}
				
	}
	
}